package com.study.poolftp;

import cn.hutool.extra.ftp.Ftp;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PreDestroy;
import java.time.Duration;
import java.util.Objects;

/**
 * @author zhuzi
 * 2022/8/28 10:15
 */
@Slf4j
@Configuration
public class FtpConfig {

    private final FtpClientProperties ftpClientProperties;
    private GenericObjectPool<Ftp> pool;

    @Autowired
    public FtpConfig(FtpClientProperties ftpClientProperties) {
        this.ftpClientProperties = ftpClientProperties;
    }

    private void preLoadingFtpClient(Integer initialSize, int maxIdel) {
        if (null == initialSize || initialSize <= 0) {
            return;
        }
        int size = Math.min(initialSize, maxIdel);
        try {
            for (int i = 0; i < size; i++) {
                pool.addObject();
            }
        } catch (Exception e) {
            log.error("预加载失败!", e);
        }
    }

    @PreDestroy
    public void destory() {
        if (Objects.nonNull(pool)) {
            pool.close();
            log.info("销毁FTP客户端连接池");
        }
    }

    @Bean
    @ConditionalOnMissingBean(FtpProcessor.class)
    public FtpProcessor ftpProcessor() {
        //GenericObjectPool<Ftp> poolConfig = new GenericObjectPool<Ftp>();
        GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
        // 最大空闲数
        poolConfig.setMaxIdle(5);
        // 最小空闲数, 池中只有一个空闲对象的时候，池会在创建一个对象，并借出一个对象，从而保证池中最小空闲数为1
        poolConfig.setMinIdle(1);
        // 最大池对象总数
        poolConfig.setMaxTotal(8);
        // 逐出连接的最小空闲时间 默认1800000毫秒(30分钟)
        poolConfig.setMinEvictableIdleTimeMillis(1800000);
        // 逐出扫描的时间间隔(毫秒) 如果为负数,则不运行逐出线程, 默认-1
        poolConfig.setTimeBetweenEvictionRuns(Duration.ofMinutes(20));
        // 在获取对象的时候检查有效性, 默认false
        poolConfig.setTestOnBorrow(true);
        // 在归还对象的时候检查有效性, 默认false
        poolConfig.setTestOnReturn(true);
        // 在空闲时检查有效性, 默认false
        poolConfig.setTestWhileIdle(true);
        // 最大等待时间， 默认的值为-1，表示无限等待。
        //poolConfig.setMaxWaitMillis(5000);
        // 是否启用后进先出, 默认true
        poolConfig.setLifo(true);
        // 连接耗尽时是否阻塞, false报异常,ture阻塞直到超时, 默认true
        poolConfig.setBlockWhenExhausted(true);
        // 每次逐出检查时 逐出的最大数目 默认3
        poolConfig.setNumTestsPerEvictionRun(5);
        pool = new GenericObjectPool<>(new FtpClientFactory(ftpClientProperties), poolConfig);
        preLoadingFtpClient(15, 8);
        return new FtpProcessor(pool);
    }

}
